home *** CD-ROM | disk | FTP | other *** search
- Subject: problems with arc shapes
- Sent: 7/29/96 8:53 AM
- Received: 7/29/96 9:01 AM
- From: Uwe Schoeneberg, odf@softgene.spacenet.de
- Reply-To: ODF Interest, ODF-Interest@CILabs.ORG
- To: OpenDoc Development Framework Discussion List, ODF-Interest@CILabs.
-
- I guess this a bug in how ODF handles arcs:
-
- I was playing around with arc shapes and I thought
-
- FW_CArcShape::RenderArc(gc, rect,
- startAngle, arcAngle,
- FW_kFill, fFillInk, fFillStyle);
-
- should have the same result on the screen as
-
- FW_CAcquiredODShape aqSegmentShape =
- ::FW_CreateArcODShape(ev, rect, startAngle, arcAngle);
-
- FW_CRegionShape::RenderRegion(gc, aqSegmentShape,
- FW_kFill, fFillInk, fFillStyle);
-
- but I was wrong for startAngle == 90, 180, 270 and arcAngle == 45;
-
- During tracing from FW_CreateArcODShape into the ODFLibrary I found that,
- in SLRegion.cpp, method FW_CreateArcRegion, the polygon wasn't closed. So I
- changed
-
- ::MoveTo(pt[0].h, pt[0].v);
- for (short i = 1; i < 6; i ++)
- ::LineTo(pt[i].h, pt[i].v);
-
- to
-
- ::MoveTo(pt[5].h, pt[5].v);
- for (short i = 0; i < 6; i ++)
- ::LineTo(pt[i].h, pt[i].v);
-
-
- In addition, PrivCalcArcPoints (in PRGrUtil.cpp) does not seem to always
- return the right values in arcPoint. I would like to discuss my solution
- for PrivCalcArcPoints with [KVV]:
-
- void SL_API FW_PrivCalcArcPoints(const FW_CPlatformRect& rect,
- short angle,
- FW_CPlatformPoint& arcPoint)
- {
- FW_Fixed fxRad = (FW_IntToFixed(angle) * FW_kFixedPI) / FW_IntToFixed(180);
-
- FW_PlatformCoordinate middleX = (rect.right + rect.left) / 2;
- FW_PlatformCoordinate middleY = (rect.bottom + rect.top) / 2;
- // was rect.right + rect.left !!!
-
- const FW_Fixed halfX = FW_IntToFixed((rect.right - rect.left) / 2);
- const FW_Fixed halfY = FW_IntToFixed((rect.bottom - rect.top) / 2);
-
- short shortX = FW_FixedToInt(halfX * FW_Sin(fxRad));
- short shortY = -FW_FixedToInt(halfY * FW_Cos(fxRad));
-
- arcPoint.Set(shortX + middleX, shortY + middleY);
- }
-
- This way, FW_PrivCalcArcPoints gives a better approximation of an ellipse
- and hence FW_CreateArcRegion be changed to the following (Mac code only):
-
- ODRgnHandle SL_API FW_CreateArcRegion(const FW_SRect& rect,
- short startAngle, short arcAngle)
- {
- // No try block necessary - Do not throw
- FW_CPlatformRect plfmRect = rect;
-
- #ifdef FW_BUILD_MAC
-
- if (startAngle >= 360)
- startAngle = startAngle % 360;
- else if (startAngle < 0)
- startAngle = (startAngle % 360) + 360;
-
- if (arcAngle > 360)
- arcAngle = arcAngle % 360;
-
- if (arcAngle == 0)
- arcAngle = 360;
- else if (arcAngle < 0)
- arcAngle = (arcAngle % 360) + 360;
-
- const ODUShort anglePerSegment = 5;
- const ODUShort maxSegments = (360 / anglePerSegment) +1;
- ODUShort numSegments = arcAngle / anglePerSegment;
-
- ODUShort angle = startAngle;
- FW_CPlatformPoint pt[maxSegments]; // pt[numSegments +1]
- for (ODUShort i = 0; i <= numSegments; i++) // we create numSegments +1
- points
- {
- angle = startAngle + arcAngle * i / numSegments;
- FW_PrivCalcArcPoints(plfmRect, angle, pt[i]);
- }
-
- // Create a polygon region
- GrafPtr savePort = ::PrivMacOpenRegion();
-
- FW_CPlatformPoint center((plfmRect.left + plfmRect.right) / 2,
- (plfmRect.top + plfmRect.bottom) / 2);
- ::MoveTo(center.h, center.v);
- for(ODUShort j = 0; j <= numSegments; j++) // we have numSegments +1 points
- ::LineTo(pt[j].h, pt[j].v);
- ::LineTo(center.h, center.v);
-
- ODRgnHandle hArcRegion = ::PrivMacCloseRegion(savePort);
-
- // Return the result
- return hArcRegion;
- #endif
-
- #ifdef FW_BUILD_WIN
-
- // Windows code here
-
- #endif
- }
-
- I also found out that, in method FW_PrivRenderArc, for a renderVerb ==
- FW_kFrame the result on the screen is different for Windows and MacOS as
- FrameRgn frames the whole wedge with a region that comes out of
- ::FW_CreateArcRegion whereas FrameArc just draws an arc.
-
- Uwe Schoeneberg
-
-
- -----------------------------------------------------------------------------
- Soft Gene GmbH
- Offenbacher Str. 5
- 14 197 Berlin Tel: +49-30 841 71 50
- Germany Fax: +49-30 821 97 64
-
-
-
-
-
-